package tests

import (
	"fmt"
	"github.com/wendy512/go-iecp5/asdu"
	"time"
)

const (
	commonAddr = 1
)

type myServerHandler struct {
}

func (ms *myServerHandler) OnInterrogation(conn asdu.Connect, pack *asdu.ASDU, quality asdu.QualifierOfInterrogation) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnInterrogation \n")
	// TODO

	for i := 0; i < 100; i++ {
		var now = time.Now()
		measuredValues := []asdu.MeasuredValueFloatInfo{
			{Ioa: 0x4001, Value: 12.3 * float32(i), Qds: asdu.QDSGood, Time: now},
			{Ioa: 0x4002, Value: 22.34 * float32(i), Qds: asdu.QDSGood, Time: now},
			{Ioa: 0x4003, Value: 33.31 * float32(i), Qds: asdu.QDSGood, Time: now},
			{Ioa: 0x4004, Value: 44.34 * float32(i), Qds: asdu.QDSGood, Time: now},
			{Ioa: 0x4005, Value: 55.34 * float32(i), Qds: asdu.QDSGood, Time: now},
			{Ioa: 0x4006, Value: 66.34 * float32(i), Qds: asdu.QDSGood, Time: now},
		}
		_ = asdu.MeasuredValueFloat(conn,
			false,
			asdu.CauseOfTransmission{IsTest: false, IsNegative: false, Cause: asdu.Periodic},
			commonAddr,
			measuredValues...,
		)
		fmt.Printf("send values %v \n", time.Now())
		time.Sleep(500 * time.Millisecond)
	}

	//_ = asdu.Single(conn, false, asdu.CauseOfTransmission{Cause: asdu.InterrogatedByStation}, commonAddr, asdu.SinglePointInfo{
	//	Ioa:   100,
	//	Value: true,
	//	Qds:   asdu.QDSGood,
	//})
	//_ = asdu.Double(conn, false, asdu.CauseOfTransmission{Cause: asdu.InterrogatedByStation}, commonAddr, asdu.DoublePointInfo{
	//	Ioa:   200,
	//	Value: asdu.DPIDeterminedOn,
	//	Qds:   asdu.QDSGood,
	//})
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnCounterInterrogation(conn asdu.Connect, pack *asdu.ASDU, quality asdu.QualifierCountCall) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnCounterInterrogation \n")
	// TODO
	_ = asdu.CounterInterrogationCmd(conn, asdu.CauseOfTransmission{Cause: asdu.Activation}, commonAddr, asdu.QualifierCountCall{asdu.QCCGroup1, asdu.QCCFrzRead})
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnRead(conn asdu.Connect, pack *asdu.ASDU, addr asdu.InfoObjAddr) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnRead \n")
	// TODO
	_ = asdu.Single(conn, false, asdu.CauseOfTransmission{Cause: asdu.InterrogatedByStation}, commonAddr, asdu.SinglePointInfo{
		Ioa:   addr,
		Value: true,
		Qds:   asdu.QDSGood,
	})
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnClockSync(conn asdu.Connect, pack *asdu.ASDU, tm time.Time) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnClockSync \n")

	now := time.Now()
	_ = asdu.ClockSynchronizationCmd(conn, asdu.CauseOfTransmission{Cause: asdu.Activation}, commonAddr, now)
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnResetProcess(conn asdu.Connect, pack *asdu.ASDU, quality asdu.QualifierOfResetProcessCmd) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnResetProcess \n")
	// TODO
	_ = asdu.ResetProcessCmd(conn, asdu.CauseOfTransmission{Cause: asdu.Activation}, commonAddr, asdu.QPRGeneralRest)
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnDelayAcquisition(conn asdu.Connect, pack *asdu.ASDU, msec uint16) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnDelayAcquisition \n")
	// TODO
	_ = asdu.DelayAcquireCommand(conn, asdu.CauseOfTransmission{Cause: asdu.Activation}, commonAddr, msec)
	_ = pack.SendReplyMirror(conn, asdu.ActivationTerm)
	return nil
}

func (ms *myServerHandler) OnASDU(conn asdu.Connect, pack *asdu.ASDU) error {
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	fmt.Printf("OnASDU xxxxxxxxx  \n")
	// TODO
	cmd := pack.GetSingleCmd()
	_ = asdu.SingleCmd(conn, pack.Type, pack.Coa, pack.CommonAddr, asdu.SingleCommandInfo{
		Ioa:   cmd.Ioa,
		Value: cmd.Value,
		Qoc:   cmd.Qoc,
	})
	_ = pack.SendReplyMirror(conn, asdu.ActivationCon)
	return nil
}
